﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Ionic.Zip;

namespace Yesuo
{
    public partial class AutoUpdater : Form
    {
        private static string dirPath;
        private static long size; //所有文件大小 
        private static int count; //文件总数  
        private static int num; //已更新文件数 
        private static long upsize; //已更新文件大小 
        private static string fileName; //当前文件名 
        private static long filesize; //当前文件大小 


        public AutoUpdater()
        {
            InitializeComponent();
        }

        #region "showfunction"
        private DateTime todate(string datestr)
        {
            return Convert.ToDateTime(datestr, CultureInfo.InvariantCulture);
        }
        private bool strNE(string str)
        {
            return string.IsNullOrEmpty(str);
        }
        private static void MeBox(string txt)
        {
            MessageBox.Show(txt, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1,
                MessageBoxOptions.DefaultDesktopOnly);
        }
        #endregion


        private void ComCirUpdate_Load(object sender, EventArgs e)
        {
            dirPath = GetConfigValue(  "Url");
            string thePreUpdateDate = GetTheLastUpdateTime(dirPath);//服务器版本
            string localUpDate = GetConfigValue(  "UpDate");//本地版本

            if (strNE(thePreUpdateDate) || strNE(localUpDate))  UpdaterClose();
            if (DateTime.Compare(todate(thePreUpdateDate), todate(localUpDate)) <= 0) UpdaterClose();

        //    preDownload();//创建升级的文件夹
       //     UpdaterStart();
            
        }
  

        private string basefolder = Application.StartupPath+@"\";
        private string updateFolder = Application.StartupPath  + @"\AutoUpdater\";
        private string backFolder = Application.StartupPath + @"\Bak\";
        private string exename = "";

        private void preDownload()
        {
            if (!Directory.Exists(updateFolder)) 
            Directory.CreateDirectory(updateFolder);
            exename = ConfigurationManager.AppSettings["exeName"];
        }

        //备份旧文件
        private void BackFile()
        {
            if (!Directory.Exists(backFolder))
                Directory.CreateDirectory(backFolder);  

            DirectoryInfo di = new DirectoryInfo(basefolder);
            FileInfo[] files = di.GetFiles();
            foreach (FileInfo fi in files)
            {
                File.Copy(basefolder + fi.Name, backFolder + fi.Name, true);
            }
            DirectoryInfo[] entry = di.GetDirectories();
            foreach (DirectoryInfo info in entry)
            {
                Directory.Move(info.FullName,backFolder);
            }
        }

        private void UpdateFile()
        {
            BackFile();
            DownloadFile();
            unpackFile();
            SetConfigValue("UpDate", GetTheLastUpdateTime(dirPath));
            UpdaterClose();
        }

        private void DownloadFile()
        {
            throw new NotImplementedException();
        }
        private void unpackFile()
        {
            DirectoryInfo di = new DirectoryInfo(updateFolder);
            FileInfo[] files = di.GetFiles();
            foreach (FileInfo fi in files)
            {
                //如果是压缩包,那么解压到升级目录,然后再解压
                if (fi.Extension.ToLower() == ".zip")
                {
                    string unpackDirectory = updateFolder;
                    using (ZipFile zip1 = ZipFile.Read(fi.FullName))
                        foreach (ZipEntry e in zip1)
                        {
                            e.Extract(unpackDirectory, ExtractExistingFileAction.OverwriteSilently);
                        }
                }
            }

         
            FileInfo[] files2 = di.GetFiles();
            foreach (FileInfo fi in files2)
            {
                if (fi.Extension.ToLower() == ".zip") continue;
                File.Copy(updateFolder + fi.Name, basefolder + fi.Name, true);
            } 

        }
     


        /// <summary>
        ///     获取更新文件大小统计
        /// </summary>
        /// <param name="filePath">更新文件数据XML</param>
        /// <returns>返回值</returns>
        private static long GetUpdateSize(string filePath)
        {
            long len = 0;
            try
            {
                var wc = new WebClient();
                Stream sm = wc.OpenRead(filePath);
                var xr = new XmlTextReader(sm);
                while (xr.Read())
                {
                    if (xr.Name == "UpdateSize")
                    {
                        len = Convert.ToInt64(xr.GetAttribute("Size"), CultureInfo.InvariantCulture);
                        break;
                    }
                }
                xr.Close();
                sm.Close();
            }
            catch (WebException ex)
            {
                MeBox(ex.Message);
            }
            return len;
        }

        /// <summary>
        ///     获取文件列表并下载
        /// </summary>
        private   ArrayList  UpdateList()
        {
            string xmlPath = dirPath + "AutoUpdater/AutoUpdater.xml";
            var wc = new WebClient();
            ArrayList ar = new ArrayList();
            Stream sm = wc.OpenRead(xmlPath);
            try
            {
                XmlDocument xml = new XmlDocument();
                xml.Load(sm);
                XmlNodeList nodelist = xml.SelectNodes("/AutoUpdater/UpdateFileList/UpdateFile");
                foreach (XmlNode node in nodelist)
                {
                    ar.Add(node.Attributes["FileName"].Value);
                } 
            }
            catch (WebException ex)
            {
                MeBox(ex.Message);
            }
           
            return ar;
        }

      

        /// <summary>
        ///     转换字节大小
        /// </summary>
        /// <param name="byteSize">输入字节数</param>
        /// <returns>返回值</returns>
        private static string ConvertSize(long byteSize)
        {
            string str;
            float tempf = byteSize;
            if (tempf/1024 > 1)
                if ((tempf/1024)/1024 > 1)
                    str = ((tempf/1024)/1024).ToString("##0.00", CultureInfo.InvariantCulture) + "MB";
                else
                    str = (tempf/1024).ToString("##0.00", CultureInfo.InvariantCulture) + "KB";
            else
                str = tempf.ToString(CultureInfo.InvariantCulture) + "B";
             
            return str;
        }

    



        /// <summary>
        ///     关闭程序
        /// </summary>
        private   void UpdaterClose()
        {
            try
            {
                Process.Start( basefolder+ exename );
            }
            catch (Win32Exception ex)
            {
                MeBox(ex.Message);
            }
            Application.Exit();
        }

        /// <summary>
        ///     读取.exe.config的值
        /// </summary>
        /// <param name="path">.exe.config文件的路径</param>
        /// <param name="appKey">"key"的值</param>
        /// <returns>返回"value"的值</returns>
        public   string GetConfigValue( string appKey)
        {
            return ConfigurationManager.AppSettings[appKey];
        } 
 
        public void SetConfigValue(  string appKey, string appValue)
        { 
            try
            {
                Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                cfa.AppSettings.Settings[appKey].Value = appValue;
                cfa.Save();
            }
            catch (Exception  ex)
            {
                MeBox(ex.Message);
            }
        }

        /// <summary>
        ///     判断软件的更新日期
        /// </summary>
        /// <param name="Dir">服务器地址</param>
        /// <returns>返回日期</returns>
        private   string GetTheLastUpdateTime(string Dir)
        {
            string lastUpdateTime = "";
            string autoUpdaterFileName = Dir + "AutoUpdater/AutoUpdater.xml";
            try
            {
                var wc = new WebClient();
                Stream sm = wc.OpenRead(autoUpdaterFileName);
                var xml = new XmlTextReader(sm);
                while (xml.Read())
                {
                    if (xml.Name == "UpdateTime")
                    {
                        lastUpdateTime = xml.GetAttribute("Date");
                        break;
                    }
                }
                xml.Close();
                sm.Close();
            }
            catch (WebException ex)
            {
                MeBox(ex.Message);
            }
            return lastUpdateTime;
        }

        private void DownloadProgressChanged(object wcsender, DownloadProgressChangedEventArgs ex)
        {
            float tempf;
            label2.Text = String.Format(CultureInfo.InvariantCulture, "正在下载:{0}  [ {1}/{2} ]", fileName, ConvertSize(ex.BytesReceived), ConvertSize(ex.TotalBytesToReceive));
            Debug.WriteLine(DateTime.Now);

        //    filesize = ex.TotalBytesToReceive;
        //    tempf = ((float)(upsize + ex.BytesReceived) / size);
         //   progressBar1.Value = Convert.ToInt32(tempf * 100);
         //   progressBar2.Value = ex.ProgressPercentage;
            progressBar1.Value = 100;
        }  

        
        private void btn_update_Click(object sender, EventArgs e)
        {
            btn_update.Enabled = false; 
            preDownload(); 
            dirPath = GetConfigValue("Url");
            string thePreUpdateDate = GetTheLastUpdateTime(dirPath);//服务器版本 
            size = GetUpdateSize(dirPath + "aupdate.php");
            preDownload();
            if (size == 0)
            {
                UpdaterClose();
                return;
            }
         
            ArrayList ar = UpdateList();  
            try
            {
                num = 0;
                foreach (string ts in ar)
                {     
                    WebClient downWebClient = new WebClient();
                    Debug.WriteLine(ts);
                    num++;
                    fileName = ts;
                    label1.Text = String.Format(CultureInfo.InvariantCulture, "更新进度 {0}/{1}  [ {2} ]", num, count, ConvertSize(size));
                    downWebClient.DownloadProgressChanged+=DownloadProgressChanged;
                    downWebClient.DownloadFile(new Uri(dirPath + "AutoUpdater/" + fileName), basefolder + "AutoUpdater\\" + fileName);
                    progressBar1.Value = 100;
                    progressBar2.Value = 100;
                }
            }
            catch (WebException ex)
            {
                MeBox(ex.Message);
            }

            unpackFile();
            btn_update.Enabled = true;
            return;

           
            BackFile();
            UpdaterClose();
            //preDownload();
        }
    }
}